%{
/*
 * HackSQL
 * Copyright (C) 2008-2009
 *
 * Authors: Felipe Nascimento Silva Pena
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $Id: hs_sql_parser.y 52 2009-03-30 01:00:01Z heuripedes $
 */

#include <stdio.h>
#include <string.h>
#include "hs_parser_common.h"
#include "hs_execute.h"

#define HS_SOCKET parser_info->socket
#define QUERY parser_info->query

#define IS_EXPRESSION(v) v.val.type = IS_EXPR

#define OP_NUM(v) v.val.data.num
#define OP_STR(v) v.val.data.str
#define OP_VAL(v) v.val
%}

%glr-parser
%pure-parser
%error-verbose
%parse-param {hs_parser_info *parser_info}

%token T_CREATE
%token T_TABLE
%token T_DOMAIN
%token T_STRING
%token T_NUMBER
%token T_SCHEMA
%token T_COLLATION
%token T_CHARACTER_SET
%token T_ASSERTION
%token T_VIEW
%token T_TRANSACTION
%token T_IS
%token T_NOT
%token T_AND
%token T_OR
%token T_CHECK
%token T_LIKE
%token T_IN
%token T_NULL
%token T_DEFAULT
%token T_UNKNOWN
%token T_INSERT
%token T_INTO
%token T_VALUES
%token T_ALL
%token T_EXCEPT
%token T_UNION
%token T_INTERSECT
%token T_INSERT
%token T_SELECT
%token T_MODULE
%token T_BY
%token T_CORRESPONDING
%token T_CROSS_JOIN
%token T_INNER
%token T_ON
%token T_NATURAL
%token T_AS
%token T_JOIN
%token T_USING
%token T_OUTER
%token T_FULL
%token T_RIGHT
%token T_LEFT
%token T_TEMPORARY
%token T_GLOBAL
%token T_LOCAL
%token T_CONSTRAINT
%token T_PRESERVE
%token T_ON_COMMIT
%token T_DELETE
%token T_ROWS
%token T_BIT
%token T_VARYING
%token T_DATE
%token T_TIME
%token T_TIMESTAMP
%token T_CHAR
%token T_CHARACTER
%token T_VARCHAR
%token T_CHAR
%token T_INTEGER
%token T_NUMERIC
%token T_INT
%token T_DECIMAL
%token T_DEC
%token T_SMALLINT
%token T_FLOAT
%token T_DOUBLE
%token T_REAL
%token T_BOOL
%token T_BLOB
%token T_TO
%token T_INTERVAL
%token T_SECOND
%token T_DAY
%token T_MONTH
%token T_HOUR
%token T_MINUTE
%token T_YEAR
%token T_SESSION_USER
%token T_USER
%token T_SYSTEM_USER
%token T_CURRENT_USER
%token T_DISTINCT
%token T_ALL
%token T_AS
%token T_FROM
%token T_WHERE
%token T_GROUP
%token T_BY
%token T_COLLATE
%token T_HAVING
%token T_OP_EQUAL
%token T_OP_NOT_EQUAL
%token T_OP_LESS_THAN
%token T_OP_GREATER_THAN
%token T_OP_GREATER_THAN_OR_EQUAL
%token T_OP_LESS_THAN_OR_EQUAL
%token T_OP_CONCAT
%token T_BETWEEN
%token T_LIKE
%token T_ESCAPE
%token T_FOR
%token T_SUBSTRING
%token T_LOWER
%token T_UPPER
%token T_TRIM
%token T_CONVERT
%token T_USING
%token T_LEADING
%token T_BOTH
%token T_TRAILING
%token T_TRANSLATE
%token T_POSITION
%token T_SECOND
%token T_EXTRACT
%token T_CHARACTER
%token T_LENGTH
%token T_CHAR_LENGTH
%token T_CHARACTER_LENGTH
%token T_OCTET_LENGTH
%token T_BIT_LENGTH
%token T_VARYING
%token T_CHAR
%token T_BIT
%token T_OCTET
%token T_TIMEZONE
%token T_AT
%token T_TIMEZONE_HOUR
%token T_TIMEZONE_MINUTE
%token T_UNIQUE
%token T_EXISTS
%token T_MATCH
%token T_PARTIAL
%token T_OVERLAPS
%token T_VALUE
%token T_INDICATOR
%token T_CAST
%token T_COALESCE
%token T_NULLIF
%token T_COUNT
%token T_CASE
%token T_END
%token T_ELSE
%token T_WHEN
%token T_THEN
%token T_AVG
%token T_MIN
%token T_MAX
%token T_SUM
%token T_SET
%token T_CURRENT
%token T_OF
%token T_UPDATE
%token T_WITH
%token T_OPTION
%token T_GRANT
%token T_ALL_PRIVILEGES
%token T_USAGE
%token T_WRITE
%token T_REFERENCES
%token T_PUBLIC
%token T_TRANSLATION
%token T_COMMIT
%token T_ROLLBACK
%token T_WORK
%token T_ISOLATION
%token T_LEVEL
%token T_READ
%token T_ONLY
%token T_DIAGNOSTICS
%token T_SIZE
%token T_READ
%token T_UNCOMMITTED
%token T_COMMITTED
%token T_REPEATABLE
%token T_SERIALIZABLE
%token T_CHECK_OPTION
%token T_WITH
%token T_CASCADED
%token T_DEFERRABLE
%token T_INITIALLY
%token T_IMMEDIATE
%token T_INITIALLY
%token T_DEFERRED
%token T_AUTHORIZATION
%token T_NO
%token T_PAD
%token T_SPACE
%token T_GET
%token T_DESC
%token T_EXTERNAL
%token T_IDENTITY
%token T_CURRENT_DATE
%token T_CURRENT_TIME
%token T_CURRENT_TIMESTAMP
%token T_TRUE
%token T_FALSE
%token T_DESCRIBE
%token T_REVOKE
%token T_OPTION
%token T_CASCADE
%token T_RESTRICT
%token T_PRIMARY
%token T_KEY
%token T_NO
%token T_ACTION
%token T_DROP
%token T_ALTER
%token T_ADD
%token T_COLUMN

%nonassoc '(' ')'

%%

start:
		stmt ';'
;

stmt:
		create_stmt
	|	insert_stmt
	|	select_stmt { hs_select_result(parser_info); }
	|	update_stmt
	|	delete_stmt
	|	commit_stmt
	|	rollback_stmt
	|	set_transaction_stmt
	|	sql_schema_definition_stmt
	|	sql_schema_manipulation_stmt
	|	describe_statement { hs_describe(HS_SOCKET, &$1); }
;

not_optional:
		/* empty */
	|	T_NOT
;

value_expression:
		numeric_value_expression { $$ = $1; IS_EXPRESSION($$); }
		/*
	|	string_value_expression
	|	datetime_value_expression
	|	interval_value_expression*/
;

in_value_list:
		value_expression
	|	in_value_list ',' value_expression
;

in_predicate_value:
		subquery
	|	'(' in_value_list ')'
;

row_value_constructor:
		row_value_constructor_element
;

null_specification:
		T_NULL
;

default_specification:
		T_DEFAULT
;

row_value_constructor_element:
		value_expression
	|	null_specification
	|	default_specification
;

in_predicate:
		row_value_constructor not_optional T_IN in_predicate_value
;

comp_op:
		T_OP_EQUAL
	|	T_OP_NOT_EQUAL
	|	T_OP_LESS_THAN
	|	T_OP_GREATER_THAN
	|	T_OP_GREATER_THAN_OR_EQUAL
	|	T_OP_LESS_THAN_OR_EQUAL
;

trim_function:
		T_TRIM '(' trim_operands ')'
;

comparison_predicate:
		row_value_constructor comp_op row_value_constructor
;

between_predicate:
		row_value_constructor not_optional T_BETWEEN row_value_constructor T_AND row_value_constructor
;

character_value_expression:
		concatenation
	|	character_factor
;

sign_optional:
		/* empty */
	|	'+'
	|	'-'
;

position_expression:
		T_POSITION '(' character_value_expression T_IN character_value_expression ')'
;

extract_field:
		datetime_field
	|	time_zone_field
;

extract_source:
		datetime_value_expression
	|	interval_value_expression
;

datetime_field:
		non_second_datetime_field
	|	T_SECOND
;

extract_expression:
		T_EXTRACT '(' extract_field T_FROM extract_source ')'
;

numeric_value_function:
		position_expression
	|	extract_expression
	|	length_expression
;

length_expression:
		char_length_expression
	|	octet_length_expression
	|	bit_length_expression
;

char_length_expression:
		T_CHAR T_LENGTH '(' string_value_expression ')'
	|	T_CHARACTER_LENGTH '(' string_value_expression ')'
;

octet_length_expression:
		T_OCTET_LENGTH '(' string_value_expression ')'
;

datetime_primary:
		value_expression_primary
	|	datetime_value_function
;

string_value_expression:
		character_value_expression
	|	bit_value_expression
;

interval_term:
		interval_factor
	|	interval_term_2 '*' factor
	|	interval_term_2 '/' factor
	|	term '*' interval_factor
;

interval_term_2:
		interval_term
;

interval_item:
		interval_factor
	|	interval_term_2 '*' factor
	|	interval_term_2 '/' factor
	|	term '*' interval_factor
;

interval_factor:
		sign_optional interval_primary
;

interval_leading_field_precision:
		unsigned_integer
;

interval_qualifier_optional:
		start_field T_TO end_field
	|	single_datetime_field
;

interval_primary:
		value_expression_primary interval_qualifier_optional
;

bit_length_expression:
		T_BIT_LENGTH '(' string_value_expression ')'
;

numeric_primary:
		value_expression_primary { $$ = $1; }
	|	numeric_value_function { $$ = $1; }
;

factor:
		sign_optional numeric_primary { $$ = $2; }
;

term: 
		factor { $$ = $1; }
	|	term '*' factor { $$ = $1; OP_NUM($$) = OP_NUM($1) * OP_NUM($2); }
	|	term '/' factor { $$ = $1; OP_NUM($$) = OP_NUM($1) / OP_NUM($2); }
;

numeric_value_expression:
		term { $$ = $1; }
	|	numeric_value_expression '+' term { $$ = $1; OP_NUM($$) = OP_NUM($1) + OP_NUM($3); }
	|	numeric_value_expression '-' term { $$ = $1; OP_NUM($$) = OP_NUM($1) - OP_NUM($3); }
;

unsigned_literal:
		unsigned_numeric_literal { $$ = $1; }
	|	general_literal { $$ = $1; }
;

question_mark:
		'?'
;

parameter_name:
		':' identifier
;

dynamic_parameter_specification:
		question_mark
;

indicator_parameter:
		T_INDICATOR parameter_name
	|	parameter_name
;

embedded_variable_name:
		':' host_identifier
;

host_identifier:
		/*todo*/
;

indicator_variable_optional:
		embedded_variable_name
	|	T_INDICATOR embedded_variable_name
;

variable_specification:
		embedded_variable_name indicator_variable_optional
;

indicator_parameter_optional:
		/* empty */
	|	indicator_parameter
;

parameter_specification:
		parameter_name indicator_parameter_optional
;

general_value_specification:
		parameter_specification
	|	dynamic_parameter_specification
	|	variable_specification
	|	T_USER
	|	T_CURRENT_USER
	|	T_SESSION_USER
	|	T_SYSTEM_USER
	|	T_VALUE
;

unsigned_value_specification:
		unsigned_literal { $$ = $1; }
	|	general_value_specification { $$ = $1; }
;

cast_operand:
		value_expression
	|	T_NULL	
;

type_name:
		T_INTEGER
	|	T_INT
	|	T_VARCHAR
	|	T_CHAR
	|	T_BLOB
	|	T_BOOL
	|	T_DOUBLE
	|	T_REAL
;

cast_target:
		domain_name
	|	type_name
;

domain_name:
		qualified_name
;

coalesce_repeated_optional:
		/* empty */
	|	coalesce_repeated_optional ',' value_expression
;

scalar_subquery:
		subquery
;

set_function_specification:
		T_COUNT '(' '*' ')'
	|	general_set_function
;

general_set_function:
		set_function_type '(' set_quantifier_optional value_expression ')'
;

case_abbreviation:
		T_NULLIF '(' value_expression ',' value_expression ')'
	|	T_COALESCE '(' value_expression coalesce_repeated_optional ')'
;

case_specification:
		simple_case
	|	searched_case
;

else_clause_optional:
		/* empty */
	|	T_ELSE result
;

result:
		result_expression
	|	T_NULL
;

result_expression:
		value_expression
;

case_operand:
		value_expression
;

simple_when_clause:
		T_WHEN when_operand T_THEN result
;

set_function_type:
		T_AVG
	|	T_MAX
	|	T_MIN
	|	T_SUM
	|	T_COUNT
;

when_operand:
		value_expression
;

searched_when_clause:
		T_WHEN search_condition T_THEN result
;

searched_case:
		T_CASE searched_when_clause else_clause_optional T_END
	|	T_CASE searched_when_clause T_END
;

simple_case:
		T_CASE case_operand simple_when_clause else_clause_optional T_END
;

case_expression:
		case_abbreviation
	|	case_specification
;

cast_specification:
		T_CAST '(' cast_operand T_AS cast_target ')'
;

value_expression_primary:
		unsigned_value_specification { $$ = $1; }
	|	column_reference { $$ = $1; }
	|	set_function_specification { $$ = $1; }
	|	scalar_subquery { $$ = $1; }
	|	case_expression { $$ = $1; }
	|	'(' value_expression ')' { $$ = $2; }
	|	cast_specification { $$ = $1; }
;

datetime_term:
		datetime_factor
;

time_zone_specifier:
		T_LOCAL	interval_value_expression
	|	T_TIMEZONE interval_value_expression
;

interval_value_expression:
		interval_term
	|	interval_value_expression '+' interval_term_1
	|	interval_value_expression '-' interval_term_1
	|	'(' datetime_value_expression '-' datetime_term ')' interval_qualifier
;

interval_term_1:
		interval_term
;

time_zone_optional:
		/* empty */
	|	T_AT time_zone_specifier
;

datetime_factor:
		datetime_primary time_zone_optional
;

datetime_value_expression:
		datetime_term
	|	interval_value_expression '+' datetime_term
	|	datetime_value_expression '+' interval_item
	|	datetime_value_expression '-' interval_item
;

length_expression:
		char_length_expression
	|	octet_length_expression
	|	bit_length_expression
;

bit_value_function:
		bit_substring_function
;

for_optional:
		/* empty */
	|	T_FOR string_length
;

string_length:
		numeric_value_expression
;

bit_factor:
		bit_primary
;

bit_value_expression:
		bit_concatenation
	|	bit_factor
;

bit_substring_function:
		T_SUBSTRING '(' bit_value_expression T_FROM start_position for_optional ')'
;

character_substring_function:
		T_SUBSTRING '(' character_value_expression T_FROM start_position for_optional ')'
;

fold:
		T_UPPER '(' character_value_expression ')'
	|	T_LOWER '(' character_value_expression ')'
;

start_position:
		numeric_value_expression
;

concatenation_operator:
		T_OP_CONCAT
;

bit_concatenation:
		bit_value_expression concatenation_operator bit_factor
;

bit_primary:
		value_expression_primary
	|	string_value_function
;

character_translation:
		T_TRANSLATE '(' character_value_expression T_USING translation_name ')'
;

translation_name:
		qualified_name
;

trim_specification:
		T_LEADING
	|	T_TRAILING
	|	T_BOTH
;

trim_source:
		character_value_expression
;

trim_character:
		character_value_expression
;

trim_operands_from:
		trim_specification trim_character T_FROM
	|	trim_specification T_FROM
	|	trim_character T_FROM
;

trim_operands:
		trim_operands_from trim_source
	|	trim_source
;

time_zone_field:
		T_TIMEZONE_HOUR
	|	T_TIMEZONE_MINUTE
;

form_of_use_conversion_name:
		qualified_name
;

form_of_use_conversion:
		T_CONVERT '(' character_value_expression T_USING form_of_use_conversion_name ')'
;

character_value_function:
		character_substring_function
	|	fold
	|	form_of_use_conversion
	|	character_translation
	|	trim_function
;

string_value_function:
		character_value_function
	|	bit_value_function
;

character_primary:
		value_expression_primary
	|	string_value_function
;

character_factor:
		character_primary collate_clause_optional
;

concatenation:
		character_value_expression concatenation_operator character_factor
;

escape_optional:
		/* empty */
	|	T_ESCAPE escape_character
;

match_value:
		character_value_expression
;

pattern:
		character_value_expression
;

escape_character:
		character_value_expression
;

like_predicate:
		match_value not_optional T_LIKE pattern escape_optional
;

null_predicate:
		T_IS not_optional T_NULL
;

quantified_comparison_predicate:
		row_value_constructor comp_op quantifier table_subquery
;

table_subquery:
		subquery
;

exists_predicate:
		T_EXISTS table_subquery
;

unique_optional:
		/* empty */
	|	T_UNIQUE
;

partial_or_full_optional:
		/* empty */
	|	T_PARTIAL
	|	T_FULL
;

match_predicate:
		row_value_constructor T_MATCH unique_optional partial_or_full_optional table_subquery
;

overlaps_predicate:
		row_value_constructor T_OVERLAPS row_value_constructor
;

predicate:
		comparison_predicate
	|	between_predicate
	|	in_predicate
	|	like_predicate
	|	null_predicate
	|	quantified_comparison_predicate
	|	exists_predicate
	|	match_predicate
	|	overlaps_predicate
;

boolean_primary:
		predicate
	|	'(' search_condition ')'
;

truth_value:
		T_TRUE
	|	T_FALSE
	|	T_UNKNOWN
;

optional_is_not_truth_value:
		/* empty */
	|	T_IS not_optional truth_value
;

boolean_test:
		boolean_primary optional_is_not_truth_value
;

boolean_factor:
		not_optional boolean_test
;

boolean_term:
		boolean_factor
	|	boolean_term T_AND boolean_factor
;

search_condition:
		boolean_term
	|	search_condition T_OR boolean_term
;

assertion_check:
		T_CHECK '(' search_condition ')'
;

unsigned_integer:
		T_NUMBER { $$ = $1; }
;

bit_string_type_optional:
		'(' unsigned_integer ')'
;

bit_string_type:
		T_BIT bit_string_type_optional
	|	T_BIT T_VARYING bit_string_type_optional
;

character_set_specification:
		'.'
;

character_set_optional:
		/* empty */
	|	T_CHARACTER_SET character_set_specification
;

national_character_string_type:
		'.'
;

datetime_type:
		T_DATE
	|	T_TIME '.'
	|	T_TIMESTAMP
;

type_size_optional:
		/* empty */
	|	'(' unsigned_integer ')'
;

type_size_optional_2:
		/* empty */
	|	'(' unsigned_integer ',' unsigned_integer ')'
	|	'(' unsigned_integer ')'
;

character_string_type:
		T_CHARACTER type_size_optional
	|	T_CHAR type_size_optional
	|	T_CHARACTER T_VARYING type_size_optional
	|	T_CHAR T_VARYING type_size_optional
	|	T_VARCHAR type_size_optional
;

exact_numeric_type:
		T_NUMERIC type_size_optional_2
	|	T_DECIMAL type_size_optional_2
	|	T_DEC type_size_optional_2
	|	T_INTEGER
	|	T_INT
	|	T_SMALLINT
;

precision_optional:
		/* empty */
	|	'(' unsigned_integer ')'
;

approximate_numeric_type:
		T_FLOAT precision_optional
	|	T_REAL
	|	T_DOUBLE
;

numeric_type:
		exact_numeric_type
	|	approximate_numeric_type
;

start_field:
		non_second_datetime_field '(' interval_leading_field_precision ')'
	|	non_second_datetime_field
;

interval_fractional_seconds_precision:
		unsigned_integer
;

end_field:
		non_second_datetime_field
	|	T_SECOND '(' interval_fractional_seconds_precision ')'
	|	T_SECOND
;

non_second_datetime_field:
		T_YEAR
	|	T_MONTH
	|	T_DAY
	|	T_HOUR
	|	T_MINUTE
;

single_datetime_field:
		non_second_datetime_field '(' unsigned_integer ')'
	|	non_second_datetime_field
	|	T_SECOND '(' unsigned_integer ',' '(' unsigned_integer ')'
	|	T_SECOND '(' unsigned_integer ')'
	|	T_SECOND
;

interval_qualifier:
		start_field T_TO end_field
	|	single_datetime_field
;

interval_type:
		T_INTERVAL interval_qualifier
;

data_type:
		character_string_type character_set_optional
	|	national_character_string_type
	|	bit_string_type
	|	numeric_type
	|	datetime_type
	|	interval_type
;

column_definition_type:
		data_type
	|	domain_name
;

constraint_name_definition:
		T_CONSTRAINT qualified_name
;

constraint_name_definition_optional:
		/* empty */
	|	constraint_name_definition
;

default_clause:
		T_DEFAULT default_option
;

current_data_value_function:
		T_CURRENT_DATE
;

time_precision:
		unsigned_integer
;

timestamp_precision:
		unsigned_integer
;

current_time_value_function:
		T_CURRENT_TIME '(' time_precision ')'
	|	T_CURRENT_TIME
;

current_timestamp_value_function:
		T_CURRENT_TIMESTAMP '(' timestamp_precision ')'
	|	T_CURRENT_TIMESTAMP
;

datetime_value_function:
		current_data_value_function
	|	current_time_value_function
	|	current_timestamp_value_function
;

signal_optional:
		/* empty */
	|	'+'
	|	'-'
;

signed_numeric_literal:
		signal_optional unsigned_numeric_literal
;

exact_numeric_literal:
		unsigned_integer '.' unsigned_integer { $$ = $1; }
	|	unsigned_integer '.' { $$ = $1; }
	|	unsigned_integer { $$ = $1; }
	|	'.' unsigned_integer { $$ = $2; }
;

signed_integer:
		signal_optional unsigned_integer
;

approximate_numeric_literal:
		exact_numeric_literal 'e' signed_integer
;

nonquote_character:
		T_STRING  /* tem que fazer no .l */
;

quote: 
		'\''
;

quote_symbol:
		quote quote
;

character_representation:
		nonquote_character
	|	quote_symbol
;

character_representation_repetition:
		quote character_representation quote
	|	character_representation_repetition quote character_representation quote
;

character_string_literal:
		'_' character_set_specification quote quote character_representation_repetition
	|	'_' character_set_specification quote quote
	|	'_' character_set_specification quote character_representation quote character_representation_repetition
	|	'_' character_set_specification quote character_representation quote
	|	quote character_representation quote character_representation_repetition
	|	quote character_representation quote
	|	quote quote character_representation_repetition
	|	quote quote
;

interval_literal:
		T_INTERVAL sign_optional interval_string interval_qualifier
;

years_value:
		datetime_value
;

months_value:
		datetime_value
;

minus_sign_optional:
		/* empty */
	|	'-'
;

year_month_literal_part_optional:
		/* empty */
	|	years_value minus_sign_optional
;

datetime_value:
		unsigned_integer
;

days_value:
		datetime_value
;

time_interval_part_optional_1:
		/* empty */
	|	':' minutes_value ':' seconds_value
	|	':' minutes_value
;

time_interval_part_optional_2:
		/* empty */
	|	':' seconds_value
;

time_interval:
		hours_value time_interval_part_optional_1
	|	minutes_value time_interval_part_optional_2
	|	seconds_value
;

hours_value:
		datetime_value
;

minutes_value:
		datetime_value
;

seconds_fraction:
		unsigned_integer
;

seconds_integer_value:
		unsigned_integer
;

seconds_value:
		seconds_integer_value '.' seconds_fraction
	|	seconds_integer_value '.'
	|	seconds_integer_value
;

day_time_interval_part_optional:
		/* empty */
	|	hours_value ':' minutes_value ':' seconds_value
	|	hours_value ':' minutes_value
	|	hours_value
;

day_time_interval:
		days_value day_time_interval_part_optional
;

day_time_literal:
		day_time_interval
	|	time_interval
;

year_month_literal:
		years_value
	|	year_month_literal_part_optional months_value
;

interval_string:
		quote year_month_literal quote
	|	quote day_time_literal quote
;

general_literal:
		character_string_literal
	/* TBD
	|	national_character_string_literal
	|	bit_string_literal
	|	hex_string_literal*/
	|	datetime_literal
	|	interval_literal
;

time_string:
		quote time_value time_zone_interval quote
;

time_literal:
		T_TIME time_string
;

datetime_literal:
		date_literal
	|	time_literal
	|	timestamp_literal
;

sign:
		'+'
	|	'-'
;

date_literal:
		T_DATE data_string
;

date_value:
		years_value '-' months_value '-' days_value
;

data_string:
		quote date_value quote
;

time_value:
		hours_value ':' minutes_value ':' seconds_value
;

timestamp_literal:
		T_TIMESTAMP timestamp_string
;

time_zone_interval:
		sign hours_value ':' minutes_value
;

timestamp_string:
		quote date_value time_value time_zone_interval quote
	|	quote date_value time_value quote
;

unsigned_numeric_literal:
		exact_numeric_literal { $$ = $1; }
	|	approximate_numeric_literal { $$ = $1; }
;

literal:
		signed_numeric_literal
	|	general_literal
;

default_option:
		literal
	|	datetime_value_function
	|	T_USER
	|	T_CURRENT_USER
	|	T_SESSION_USER
	|	T_SYSTEM_USER
	|	T_NULL
;

default_clause_optional:
		/* empty */
	|	default_clause
;

table_constraint_definition:
		constraint_name_definition_optional
;

column_constraint_optional:
		/* empty */
	|	column_constraint_definition
;

match_type:
		T_FULL
	|	T_PARTIAL
;

match_optional:
		/* empty */
	|	T_MATCH match_type
;

unique_specification:
		T_UNIQUE
	|	T_PRIMARY T_KEY
;

referential_action:
		T_CASCADE
	|	T_SET T_NULL
	|	T_SET T_DEFAULT
	|	T_NO T_ACTION
;

update_rule:
		T_ON T_UPDATE referential_action
;

delete_rule:
		T_ON T_DELETE referential_action		
;

referential_triggered_action:
		update_rule delete_rule
	|	update_rule
	|	delete_rule update_rule
	|	delete_rule
;

referential_triggered_action_optional:
		/* empty */
	|	referential_triggered_action
;

reference_column_list:
		column_name_list
;

referenced_table_and_columns:
		table_name '(' reference_column_list ')'
	|	table_name
;

references_specification:
		T_REFERENCES referenced_table_and_columns match_optional referential_triggered_action_optional
;

column_constraint:
		T_NOT T_NULL
	|	unique_specification
	|	references_specification
	|	check_constraint_definition
;

column_constraint_definition:
		constraint_name_definition_optional column_constraint constraint_attributes_optional
;

column_definition:
		column_name column_definition_type default_clause_optional column_constraint_optional collate_clause_optional

table_element:
		column_definition
	|	table_constraint_definition
;

table_element_list_repetition:
		table_element
	|	table_element_list_repetition ',' table_element
;

table_element_list:
		'(' table_element_list_repetition ')'
;

table_definition_commit_optional:
		/* empty */
	|	T_ON_COMMIT T_DELETE T_ROWS
	|	T_ON_COMMIT T_PRESERVE T_ROWS
;

table_definition_temporary_optional:
		/* empty */
	|	T_GLOBAL T_TEMPORARY 
	|	T_LOCAL T_TEMPORARY
;

table_definition:
		T_CREATE table_definition_temporary_optional T_TABLE table_name table_element_list table_definition_commit_optional
;

create_stmt:
		T_CREATE T_ASSERTION T_STRING assertion_check
	|	table_definition
	|	T_CREATE T_DOMAIN T_STRING
	|	T_CREATE T_SCHEMA T_STRING
	|	T_CREATE T_TRANSACTION T_STRING
;

identifier:
		T_STRING { $$ = $1; }
;

column_name:
		identifier
;

column_name_list:
		column_name_list ',' column_name
	|	column_name
;

column_list_optional:
		/* empty */
	|	'(' column_name_list ')'
;

table_value_constructor_list:
		row_value_constructor
	|	table_value_constructor_list ',' row_value_constructor
;


table_value_constructor:
		T_VALUES '(' table_value_constructor_list ')'
;

all_optional:
		/* empty */
	|	T_ALL
;

query_specification:
		select_stmt
;

/*
qualified_local_table_name:
		T_MODULE '.' identifier
;
*/

qualified_name:
		identifier '.' identifier '.' identifier
	|	identifier '.' identifier
	|	identifier { $$ = $1; }
;

table_name:
		qualified_name { $$ = $1; }
	/*|	qualified_local_table_name */
;

explicit_table:
		T_TABLE table_name
;

simple_table:
		query_specification
	|	table_value_constructor
	| 	explicit_table
;

non_join_query_primary:
		simple_table
	|	'(' non_join_query_expression ')'
;

as_optional:
		/* empty */
	|	T_AS
;

correlation_expression_optional:
		/* empty */
	|	'(' column_name_list ')'
;

correlation_specification:
		as_optional identifier correlation_expression_optional
		{ QUERY->table_itens[QUERY->num_table_itens].alias = OP_STR($2); }
;

correlation_specification_optional:
		/* empty */ { QUERY->table_itens[QUERY->num_table_itens].alias = NULL; }
	|	correlation_specification { $$ = $1; }
;	

subquery:
		'(' query_expression ')' { $$ = $2; }
;

table_reference:
		table_name correlation_specification_optional
	{	$$ = $1;
		QUERY->table_itens[QUERY->num_table_itens].val = OP_VAL($1);
		QUERY->num_table_itens++;
	}
	|	subquery correlation_specification
	|	joined_table
;

cross_join:
		table_reference T_CROSS_JOIN table_reference
;

natural_optional:
		/* empty */
	|	T_NATURAL
;

outer_optional:
		/* empty */
	|	T_OUTER
;

outer_join_type:
		T_LEFT
	|	T_RIGHT
	|	T_FULL
;

join_type_optional:
		/* empty */
	|	T_INNER
	|	outer_join_type outer_optional
	|	T_UNION
;

join_condition:
		T_ON search_condition
;

named_columns_join:
		T_USING '(' column_name_list ')'
;

join_specification_optional:
		join_condition
	|	named_columns_join
;

qualified_join:
		table_reference natural_optional join_type_optional T_JOIN table_reference join_specification_optional
;

joined_table:
		cross_join
	|	qualified_join
	|	'(' joined_table ')'
;

query_term:
		non_join_query_term
	|	joined_table
;

non_join_query_term:
		non_join_query_primary
	|	query_term T_INTERSECT all_optional
;

corresponding_spec_by_optional:
		/* empty */
	|	T_BY '(' column_name_list ')'
;

corresponding_spec:
		T_CORRESPONDING corresponding_spec_by_optional
;

non_join_query_expression:
		non_join_query_term
	|	query_expression T_UNION all_optional corresponding_spec query_term
	|	query_expression T_EXCEPT all_optional corresponding_spec query_term
;

query_expression:
		non_join_query_expression
	|	joined_table
;

insert_columns_and_source:
		column_list_optional query_expression
;

insert_stmt:
		T_INSERT T_INTO table_name insert_columns_and_source
;

as_clause_optional:
		/* empty */ { QUERY->select_itens[QUERY->num_select_itens].alias = NULL; }
	|	T_AS column_name { QUERY->select_itens[QUERY->num_select_itens].alias = OP_STR($2); }
	|	column_name { QUERY->select_itens[QUERY->num_select_itens].alias = OP_STR($1); }
;

quantifier:
		table_name { $$ = $1; }
;

derived_column:
		value_expression as_clause_optional { $$ = $1; }
;

select_sublist:
		derived_column
	{	$$ = $1;
		QUERY->select_itens[QUERY->num_select_itens++].val = OP_VAL($1);
	}
	|	quantifier '.' '*' /* estranho */
;

set_quantifier_optional:
		/* empty */ { QUERY->distinct = 0; }
	|	T_DISTINCT { QUERY->distinct = 1; }
	|	T_ALL { QUERY->distinct = 0; }
;

select_list_repeated:
		/* empty */
	|	select_list_repeated ',' select_sublist
;

select_list:
		'*' { QUERY->all = 1; }
	|	select_sublist select_list_repeated
;

more_table_reference_optional:
		/* empty */
	|	more_table_reference_optional ',' table_reference
;

from_clause:
		T_FROM table_reference more_table_reference_optional
	{
		QUERY->dual = (QUERY->num_table_itens == 0 && strncmp(OP_STR(QUERY->table_itens[0]), "dual", sizeof("dual")-1));
	}			
;

where_clause:
		T_WHERE search_condition
;

where_clause_optional:
		/* empty */
	|	where_clause
;

column_reference:
		quantifier 
;

collation_name:
		qualified_name
;

collate_clause:
		T_COLLATE collation_name
;

collate_clause_optional:
		/* empty */
	|	collate_clause
;

grouping_column_reference:
		column_reference collate_clause_optional
;

more_grouping_column_reference_optional:
		/* empty */
	|	more_grouping_column_reference_optional ',' grouping_column_reference
;

grouping_column_reference_list:
		grouping_column_reference more_grouping_column_reference_optional
;

group_by_clause:
		T_GROUP T_BY grouping_column_reference_list
;

group_by_clause_optional:
		/* empty */
	|	group_by_clause
;

having_clause:
		T_HAVING search_condition
;

having_clause_optional:
		/* empty */
	|	having_clause
;

table_expression:
		from_clause where_clause_optional group_by_clause_optional having_clause_optional
;

select_stmt:
		T_SELECT set_quantifier_optional select_list table_expression
		{ QUERY->type = OP_SELECT; }
;

update_source:
		value_expression 
	|	null_specification
	|	T_DEFAULT
;

cursor_name:
		identifier
;

object_column:
		column_name
;

set_clause:
		object_column T_OP_EQUAL update_source
;

set_clause_list:
		set_clause
	|	set_clause_list ',' set_clause
;

update_stmt:
		T_UPDATE table_name T_SET set_clause_list T_WHERE T_CURRENT T_OF cursor_name
	|	T_UPDATE table_name T_SET set_clause_list T_WHERE search_condition
;

delete_where_optional:
		/* empty */
	|	T_WHERE search_condition
;

delete_stmt:
		T_DELETE T_FROM table_name T_WHERE T_CURRENT T_OF cursor_name
	|	T_DELETE T_FROM table_name delete_where_optional
;

grantee:
		T_PUBLIC
	|	authorization_identifier
;

grant_stmt_part_optional_1:
		/* empty */
	|	grant_stmt_part_optional_1 ',' grantee
;

grant_stmt_part_optional_2:
		/* empty */
	|	T_WITH T_GRANT T_OPTION
;

action_list:
		action
	|	action_list ',' action
;

action_insert_optional:
		/* empty */
	|	'(' privilege_column_list ')'
;

privilege_column_list:
		column_name_list
;

action_update_optional:
		/* empty */
	|	'(' privilege_column_list ')'
;

action_references_optional:
		/* empty */
	|	'(' privilege_column_list ')'
;

object_name:
		table_name
	|	T_TABLE table_name
	|	T_DOMAIN domain_name
	|	T_COLLATION collation_name
	|	T_CHARACTER T_SET character_set_name
	|	T_TRANSLATION translation_name
;

sql_language_identifier_start_optional:
		/* empty */
	|	'_'
	|	sql_language_identifier_part
;

sql_language_identifier_part:
		T_STRING
	|	digit
;

unqualified_schema_name:
		identifier
;

digit:
		T_NUMBER
;

catalog_name:
		identifier
;

schema_name:
		catalog_name '.' unqualified_schema_name
;

sql_language_identifier_start:
		T_STRING
;

authorization_identifier:
		identifier
;

sql_language_identifier:
		sql_language_identifier_start sql_language_identifier_start_optional
;

character_set_name:
		schema_name '.' sql_language_identifier
	|	sql_language_identifier
;

action:
		T_SELECT
	|	T_DELETE
	|	T_INSERT action_insert_optional
	|	T_UPDATE action_update_optional
	|	T_REFERENCES action_references_optional
	|	T_USAGE
;

privileges:
		T_ALL_PRIVILEGES
	|	action_list
;

grant_stmt:
		T_GRANT privileges T_ON object_name T_TO grantee grant_stmt_part_optional_1 grant_stmt_part_optional_2
;

commit_stmt:
		T_COMMIT
	|	T_COMMIT T_WORK
;

rollback_stmt:
		T_ROLLBACK
	|	T_ROLLBACK T_WORK
;

level_of_isolation:
		T_READ T_UNCOMMITTED
	|	T_READ T_COMMITTED
	|	T_REPEATABLE T_READ
	|	T_SERIALIZABLE
;

number_of_conditions:
		simple_value_specification
;

transaction_mode:
		isolation_level
	|	transaction_access_mode
	|	diagnostics_size
;

diagnostics_size:
		T_DIAGNOSTICS T_SIZE number_of_conditions
;

isolation_level:
		T_ISOLATION T_LEVEL level_of_isolation
;

simple_value_specification:
		parameter_name
	|	embedded_variable_name
	|	literal
;

transaction_mode_optional:
		/* empty */
	|	transaction_mode_optional ',' transaction_mode
;

transaction_access_mode:
		T_READ T_ONLY
	|	T_READ T_WRITE
;

set_transaction_stmt:
		T_SET T_TRANSACTION transaction_mode transaction_mode_optional
;

view_definition_optional_1:
		/* empty */
	|	'(' view_column_list ')'
;

levels_clause:
		T_CASCADED
	|	T_LOCAL
;

view_column_list:
		column_name_list
;

constraint_name:
		qualified_name
;

constraint_name_definition_optional:
		T_CONSTRAINT constraint_name
;

check_constraint_definition:
		T_CHECK '(' search_condition ')'
;

deferrable_optional:
		/* empty */
	|	not_optional T_DEFERRABLE
;

constraint_check_time:
		T_INITIALLY T_DEFERRED
	|	T_INITIALLY T_IMMEDIATE
;

constraint_check_time_optional:
		/* empty */
	|	constraint_check_time
;

constraint_attributes_optional:
		constraint_check_time deferrable_optional
	|	not_optional T_DEFERRABLE constraint_check_time_optional
;

domain_constraint_optional:
		constraint_name_definition_optional check_constraint_definition constraint_attributes_optional
;

levels_clause_optional:
		/* empty */
	|	levels_clause
;

view_definition_optional_2:
		T_WITH levels_clause_optional T_CHECK_OPTION
;

limited_collation_definition:
		T_COLLATION T_FROM collation_source
;

translation_collation_part_optional:
		/* empty */
	|	T_THEN T_COLLATION collation_name
;

translation_collation:
		T_TRANSLATION translation_name translation_collation_part_optional
;

collation_source:
		collating_sequence_definition
	|	translation_collation
;

schema_character_set_name:
		character_set_name
;

target_character_set_specification:
		character_set_specification
;

collating_sequence_definition:
		external_collation
	|	schema_collation_name
	|	T_DESC '(' collation_name ')'
	|	T_DEFAULT
;

translation_definition:
		T_CREATE T_TRANSLATION translation_name
			T_FOR source_character_set_specification
			T_TO target_character_set_specification
			T_FROM translation_source		
;

schema_collation_name:
		collation_name
;

external_collation:
		T_EXTERNAL '(' quote external_collation_name quote ')'
;

source_character_set_specification:
		character_set_specification
;

existing_character_set_name:
	|	schema_character_set_name
;

character_set_source:
		T_GET existing_character_set_name
;

character_set_definition_part_optional:
		collate_clause_optional
	|	limited_collation_definition
;

character_set_definition:
		T_CREATE T_CHARACTER_SET character_set_name as_optional character_set_source character_set_definition_part_optional
;

translation_specification:
		external_translation
	|	T_IDENTITY
	|	schema_translation_name
;

standard_translation_name:
		translation_name
;

schema_translation_name:
		translation_name
;

external_translation_name:
		standard_translation_name
;

assertion_definition:
		T_CREATE T_ASSERTION constraint_name assertion_check constraint_attributes_optional
;

external_translation:
		T_EXTERNAL '(' quote external_translation_name quote ')'
;

translation_source:
		translation_specification
;

view_definition:
		T_CREATE T_VIEW table_name view_definition_optional_1 T_AS query_expression view_definition_optional_2
;

domain_definition:
		T_CREATE T_DOMAIN domain_name as_optional data_type default_clause_optional domain_constraint_optional collate_clause_optional
;

schema_character_set_specification_optional:
		T_DEFAULT T_CHARACTER_SET character_set_specification
;

schema_element:
		domain_definition
	|	table_definition
	|	view_definition
	|	grant_stmt
	|	assertion_definition
	|	character_set_definition
	|	collation_definition
	|	translation_definition
;

schema_element_optional:
		/* empty */
	|	schema_element
;

schema_authorization_identifier:
		authorization_identifier
;

pad_attribute:
		T_NO T_PAD
	|	T_PAD T_SPACE
;

pad_attribute_optional:
		/* empty */
	|	pad_attribute
;

external_collation_name:
		standard_collation_name
;

standard_collation_name:
		collation_name
;

collation_definition:
		T_CREATE T_COLLATION collation_name T_FOR character_set_specification T_FROM collation_source pad_attribute_optional
;

schema_name_clause:
		schema_name
	|	T_AUTHORIZATION schema_authorization_identifier
	|	schema_name T_AUTHORIZATION schema_authorization_identifier
;
	
schema_definition:
		T_CREATE T_SCHEMA schema_name_clause schema_character_set_specification_optional schema_element_optional
;

describe_statement:
		T_DESCRIBE identifier { $$ = $2; }
	|	T_DESC identifier { $$ = $2; }
;

sql_schema_definition_stmt:
		schema_definition
	|	view_definition
	|	grant_stmt
	|	domain_definition
	|	character_set_definition
	|	collation_definition
	|	translation_definition
	|	assertion_definition
;

drop_behavior:
		T_CASCADE
	|	T_RESTRICT
;

revoke_stmt:
		T_REVOKE T_GRANT T_OPTION T_FOR privileges T_ON object_name
			T_FROM grantee grant_stmt_part_optional_1 drop_behavior
;

drop_schema_stmt:
		T_DROP T_SCHEMA schema_name drop_behavior
;

column_optional:
		/* empty */
	|	T_COLUMN
;

add_column_definition:
		T_ADD column_optional column_definition
;

set_column_default_clause:
		T_SET default_clause
;

drop_column_default_clause:
		T_DROP T_DEFAULT
;	

alter_column_action:
		set_column_default_clause
	|	drop_column_default_clause
;

alter_column_definition:
		T_ALTER column_optional column_name alter_column_action
;

drop_table_constraint_definition:
		T_DROP T_CONSTRAINT constraint_name drop_behavior
;

drop_column_definition:
		T_DROP column_optional column_name drop_behavior
;

add_table_constraint_definition:
		T_ADD table_constraint_definition
;

alter_table_action:
		add_column_definition
	|	alter_column_definition
	|	drop_column_definition
	|	add_table_constraint_definition
	|	drop_table_constraint_definition
;

alter_table_stmt:
		T_ALTER T_TABLE table_name alter_table_action
;

drop_view_stmt:
		T_DROP T_VIEW table_name drop_behavior
;

drop_table_stmt:
		T_DROP T_TABLE table_name drop_behavior
;

sql_schema_manipulation_stmt:
		drop_schema_stmt
	|	alter_table_stmt
	|	drop_table_stmt
	|	drop_view_stmt
	|	revoke_stmt
	/*|	alter_domain_stmt
	|	drop_domain_stmt
	|	drop_character_set_stmt
	|	drop_collation_stmt
	|	drop_translation_stmt
	|	drop_assertion_stmt*/
;

%%
